#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>

#include <memory>
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Socket.hpp"

using namespace socket_ns;


class TcpServer;
// using io_service_t = std::function<void(socket_sptr sockfd, InetAddr client)>;
using io_service_t = std::function<void (socket_sptr sockfd, InetAddr client)>;

class ThreadData
{
public:
    ThreadData(socket_sptr fd,InetAddr addr,TcpServer* th)
    :sockfd(fd)
    ,clientaddr(addr)
    ,self(th)
    {}
public:
    socket_sptr sockfd;
    InetAddr clientaddr;
    TcpServer* self;
};



class TcpServer
{
public:
    TcpServer(int port,io_service_t service)
    :_localaddr("0",port)
    ,_listensock(std::make_unique<TcpSocket>())
    ,_service(service)
    ,_isrunning(false)
    {
        _listensock->BuildListenSocket(_localaddr);
    }
 

    static void* HandlerSock(void *args) //IO 和 业务解耦
    {
        pthread_detach(pthread_self());
        ThreadData* td = static_cast<ThreadData*>(args);
        td->self->_service(td->sockfd,td->clientaddr);

        delete td;
        return nullptr;
    }

    void Loop()
    {
        _isrunning = true;
        // 4.不能直接收数据，先获取链接
        while (_isrunning)
        {
            InetAddr peeraddr;
            socket_sptr normalsock = _listensock->Accept(&peeraddr);
            if(normalsock == nullptr)
            {
                continue; 
            }
            // v2 多线程
            pthread_t t;
            ThreadData* td = new ThreadData(normalsock,peeraddr,this);
            pthread_create(&t ,nullptr, &HandlerSock, td);//将线程分离

        }
        _isrunning = false;
    }

    ~TcpServer()
    {
    }

private:
    InetAddr _localaddr;
    std::unique_ptr<Socket> _listensock;
    bool _isrunning;
    io_service_t _service;
};

